import com.gomefinance.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateUtils {
    
    private final static Log log = LogFactory.getLog(DateUtils.class);
    
    static final String defaultDateFormat = "yyyy-MM-dd HH:mm:ss";
    
    static final String defaultDayFormat = "yyyy-MM-dd";
    static final String defaultDayFormats = "yyyyMMdd";
    /**
     * 默认是从星期日开始的，既1=星期日<br>
     * 有的地区是从星期一开始的,那么此时只需要给 getWeek(int week)方法里的weeks[week-1] 改成weeks[week]就行了<br>
     * 所以数组最后的“星期日”不能去掉
     */
    private static final String[] weeks = {
            "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"
    };
    
    public static void copyYearMonthDay(Calendar calendar, Calendar calendar1) {
        calendar.set(1, calendar1.get(1));
        calendar.set(2, calendar1.get(2));
        calendar.set(5, calendar1.get(5));
    }
    
    public static String formatEnDate(Date date) {
        SimpleDateFormat simpledateformat = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a");
        return simpledateformat.format(date).replaceAll("\u4E0A\u5348", "AM").replaceAll("\u4E0B\u5348", "PM");
    }
    
    /**
     * @param date
     * @return 返回格式为 'yyyy-MM-dd HH:mm:ss' 的字符串
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static String getFormatedDate(Date date) {
        return getFormatedDate(date, defaultDateFormat);
    }
    
    /**
     * @param now Date 日期
     * @param format String 日期格式，例如：'yyyy-MM-dd HH:mm:ss'，'yyyy-MM-dd HH:mm'，'yyyy-MM-dd'，'yyyy年MM月dd日 HH时mm分ss秒'
     * @return String 日期时间字符串
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static String getFormatedDate(Date now, String format) {
        try {
            DateFormat df = format == null ? new SimpleDateFormat() : new SimpleDateFormat(format);
            String str = now == null ? null : df.format(now);
            return str;
        } catch (Exception e) {
            log.error("无法解析 format: " + format, e);
            return null;
        }
    }
    
    /**
     * 返回格式为 'yyyyMMdd' 的字符串
     * 
     * @param now
     * @return 返回格式为 'yyyy-MM-dd' 的字符串
     * @author 孙岩 2015-10-21 下午09:12:03
     */
    public static String getSimplesFormatDate(Date date) {
        return getFormatedDate(date, defaultDayFormats);
    }
    
    /**
     * 返回格式为 'yyyy-MM-dd' 的字符串
     * 
     * @param now
     * @return 返回格式为 'yyyy-MM-dd' 的字符串
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static String getSimpleFormatDate(Date date) {
        return getFormatedDate(date, defaultDayFormat);
    }
    
    /**
     * 返回当前时间，格式为“yyyy-MM-dd”
     * 
     * @return String
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static String getSimpleFormatedDateNow() {
        return getSimpleFormatDate(new Date());
    }
    
    /**
     * 格式为 yyyy-MM-dd HH:mm:ss
     * 
     * @return 'yyyy-MM-dd HH:mm:ss'
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static String getStandTime() {
        return getFormatedDate(new Date());
    }
    
    /**
     * 通过DATE类型得到当前DATE星期
     * 
     * @param date 当前日期
     * @return int (1~7 , 1 代表星期日, 7 代表星期六)
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static int getWeekByDate(Date date) {
        int a = 0;
        GregorianCalendar cal = new GregorianCalendar();
        try {
            cal.setTime(date);
            a = cal.get(Calendar.DAY_OF_WEEK);
        } catch (Exception ex) {
            log.error("通过Date得到week发生异常", ex);
        }
        return a;
    }
    
    public static Date parseDate(String s) {
        Date date = null;
        try {
            date = parseDate(s, new String[] {"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd"});
        } catch (Exception exception) {
            log.error(new StringBuilder().append("Pase the Date(").append(s).append(") occur errors:").append(exception.getMessage()).toString());
        }
        return date;
    }
    
    public static Date parseDate(String str, String[] parsePatterns) throws ParseException {
        return org.apache.commons.lang.time.DateUtils.parseDate(str, parsePatterns);
    }
    
    /**
     * 通过一个'yyyy-MM-dd'日期格式字符串得到 日期对象；如果转换失败返回null
     * 
     * @param date 'yyyy-MM-dd'
     * @return null or date
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static Date parseStringToDate(String date) {
        return parseStringToDate(date, defaultDayFormat);
    }
    
    /**
     * 按照指定日期格式解析字符串
     * 
     * @param date 日期字符串
     * @param format 当前日期字符串格式
     * @return null or date
     * @author 黄国庆 2011-5-6 下午09:12:03
     */
    public static Date parseStringToDate(String date, String format) {
        DateFormat df = new SimpleDateFormat(format);
        Date nowDate = null;
        try {
            nowDate = df.parse(date);
        } catch (ParseException e) {
            log.error("无法解析" + date, e);
        }
        return nowDate;
    }
    
    public static Calendar setEndDay(Calendar calendar) {
        calendar.set(11, 23);
        calendar.set(12, 59);
        calendar.set(13, 59);
        return calendar;
    }
    
    public static Calendar setStartDay(Calendar calendar) {
        calendar.set(11, 0);
        calendar.set(12, 0);
        calendar.set(13, 0);
        return calendar;
    }
    
    /***
     * *格式化时间格式
     * 
     * @param value
     * @param format
     * @return
     */
    public static Date convertString(String value, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        if (value == null)
            return null;
        try {
            return sdf.parse(value);
        } catch (Exception e) {
        }
        return null;
    }
    
    /***
     * *格式化时间格式 yyyy-MM-dd HH:mm:ss
     * 
     * @param value
     * @return
     */
    public static Date convertString(String value) {
        return convertString(value, "yyyy-MM-dd HH:mm:ss");
    }
    
    
    /***
     * *格式化时间格式 yyyy-MM-dd
     * 
     * @param value
     * @return
     */
    public static Date convertDateString(String value) {
        return convertString(value, "yyyy-MM-dd");
    }
    
    /**
     * 将指定XML日期对象转换成格式化字符串
     * 
     * @param xmlDate Date XML日期对象
     * @param datePattern String 日期格式
     * @return String
     */
    public static String getFormattedString(XMLGregorianCalendar xmlDate, String datePattern) {
        SimpleDateFormat sd = new SimpleDateFormat(datePattern);
        Calendar calendar = xmlDate.toGregorianCalendar();
        
        return sd.format(calendar.getTime());
    }
    
    /**
     * 将Calendar转成XMLGregorianCalendar
     * 
     * @param calendar
     * @return XMLGregorianCalendar
     */
    public static XMLGregorianCalendar convert2XMLCalendar(Calendar calendar) {
        try {
            DatatypeFactory dtf = DatatypeFactory.newInstance();
            return dtf.newXMLGregorianCalendar(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1,
                                               calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR),
                                               calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND),
                                               calendar.get(Calendar.MILLISECOND), calendar.get(Calendar.ZONE_OFFSET)
                                                                                   / (1000 * 60));
            
        } catch (DatatypeConfigurationException e) {
            log.error("", e);
            return null;
        }
    }
    
    /**
     * 将Date转成XMLGregorianCalendar*
     * 
     * @param date
     * @return XMLGregorianCalendar
     */
    public static XMLGregorianCalendar convert2XMLCalendar(Date date) {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(date);
        XMLGregorianCalendar gc = null;
        try {
            gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
        } catch (Exception e) {
            log.error("", e);
        }
        return gc;
    }
    
    /**
     * 比较2个日期相差几天*
     * 
     * @param fDate 小日期
     * @param oDate 大日期
     * @return
     */
    public static int daysOfTwo(Date fDate, Date oDate) {
        Calendar aCalendar = Calendar.getInstance();
        aCalendar.setTime(fDate);
        int day1 = aCalendar.get(Calendar.DAY_OF_YEAR);
        aCalendar.setTime(oDate);
        int day2 = aCalendar.get(Calendar.DAY_OF_YEAR);
        return day2 - day1;
    }
    
    
    public static Date getBeforeDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		date = calendar.getTime();
		return date;
	}
    
    
    /***
     * 获得天*
     * 
     * @param day
     * @return
     */
    public static String getDay(String day) {
        String[] aryDay = day.split(",");
        int len = aryDay.length;
        String str = "";
        for (int i = 0; i < len; ++i) {
            String tmp = aryDay[i];
            tmp = (tmp.equals("L")) ? "最后一天" : tmp;
            if (i < len - 1) {
                str = str + tmp + ",";
            } else str = str + tmp;
        }
        
        return str;
    }
    
    /**
     * 调用结算需要的预约时间格式
     * 
     * @param date
     * @return
     * @throws DatatypeConfigurationException
     */
    public static XMLGregorianCalendar translateReserveTime(Date date) {
        GregorianCalendar gcal = new GregorianCalendar();
        XMLGregorianCalendar xgcal = null;
        try {
            xgcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
        } catch (DatatypeConfigurationException e) {
            log.error("", e);
        }
        gcal.setTime(date);
        try {
            xgcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
        } catch (DatatypeConfigurationException e) {
            log.error("", e);
        }
        return xgcal;
    }
    
    /**
     * 将java.util.Date转换为java.sql.Date*
     * 
     * @param date
     * @return
     */
    public static java.sql.Date date2date(java.util.Date date) {
        java.sql.Date sd;

        if(null==date) {
            date = new java.util.Date();
        }
        sd = new java.sql.Date(date.getTime());

        return sd;
    }

    /**
     * java.sql.Timestamp对象转java.util.Date*
     *
     * @param timestamp
     * @return
     */
    public static java.util.Date timestamp2date(Timestamp timestamp) {
        Date date = null;
        try {
            date = timestamp;
        } catch (Exception e) {
            date = null;
        }
        return date;
    }

    public static String timestamp2Str(Timestamp timestamp) {
        return getSimpleFormatDate(timestamp2date(timestamp));
    }

    /**
     * java.util.Date *对象转 java.sql.Timestamp
     *
     * @param date
     * @return
     */
    public static Timestamp date2timestamp(java.util.Date date) {
        Timestamp t = new Timestamp(date.getTime());
        return t;
    }
    
    /**
     * @param date
     * @param a (1-年、2-月、3-周、5-天)
     * @param b (正数表示加，负数表示减)
     * @return Date
     * @author 刘文斌 2014-8-22 下午5:19:20 日期按年月周日的增减计算
     */
    public static Date dateAddSub(Date date, int a, int b) {
        GregorianCalendar gc = new GregorianCalendar();
        
        gc.setTime(date);
        gc.add(a, b);
        gc.getTime();
        return gc.getTime();
    }
    
    /**
     * 时分秒比较
     * 
     * @author xuepinglu
     * @return
     */
    public static boolean compareHMS(String target, String reserveTime) {
        boolean flag = true;
        try {
            Date reserveTimeD = DateUtils.convertString(reserveTime, "HH:mm:ss");
            Date targetD = DateUtils.convertString(target, "HH:mm:ss");
            Calendar reserveTimeCal = Calendar.getInstance();
            reserveTimeCal.setTime(reserveTimeD);
            int reserveTimeHour = reserveTimeCal.get(Calendar.HOUR);// 时
            int reserveTimeMinute = reserveTimeCal.get(Calendar.MINUTE);// 分
            int reserveTimeSecond = reserveTimeCal.get(Calendar.SECOND);// 秒
            Calendar targetCal = Calendar.getInstance();
            targetCal.setTime(targetD);
            int targetHour = targetCal.get(Calendar.HOUR);// 时
            int targetMinute = targetCal.get(Calendar.MINUTE);// 分
            int targetSecond = targetCal.get(Calendar.SECOND);// 秒
            if (reserveTimeHour > targetHour) {
                flag = false;
                return flag;
            } else if (reserveTimeHour == targetHour && reserveTimeMinute > targetMinute) {
                flag = false;
                return flag;
            } else if (reserveTimeHour == targetHour && reserveTimeMinute == targetMinute
                       && reserveTimeSecond > targetSecond) {
                flag = false;
                return flag;
            } else if (0 == reserveTimeHour) {
                flag = true;
                return flag;
            }
        } catch (Exception e) {
            flag = false;
            return flag;
        }
        
        return flag;
    }
    
    /**
     * 将Date(yyyy-MM-dd HH:mm:ss)类型的日期转换成Date(yyyy-MM-dd)
     * 
     * @author xuepinglu
     * @param date
     * @return
     */
    public static Date datetimesToDate(Date date) {
        if (null == date) {
            date = new Date();
        }
        try {
            return parseStringToDate(DateUtils.getFormatedDate(date, "yyyy-MM-dd"));
        } catch (Exception e) {
            log.error("转换错误" + date, e);
        }
        return parseStringToDate(DateUtils.getFormatedDate(new Date(), "yyyy-MM-dd"));
    }
    
    /**
     * 得到中文日期格式 如果有异常，则返回null <br>
     * 返回格式："2014年9月19日星期五" 字符串
     * 
     * @return 当前系统日期的格式化字符串
     * @author guannan.shang
     */
    public static String getCNDateNow() {
        return formatDateCn(Calendar.getInstance());
    }
    
    /**
     * 得到中文日期格式 如果有异常，则返回null <br>
     * "2014年9月19日星期五" 字符串
     * 
     * @param date 要格式化的日期
     * @return 指定日期的格式化字符串
     * @author guannan.shang
     */
    public static String getCNDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return formatDateCn(cal);
    }
    
    /**
     * @param cal
     * @return
     * @author guannan.shang
     */
    private static String formatDateCn(Calendar cal) {
        try {
            StringBuffer str = new StringBuffer();
            str.append(cal.get(Calendar.YEAR)).append("年");
            str.append(cal.get(Calendar.MONTH) + 1).append("月");
            str.append(cal.get(Calendar.DATE)).append("日");
            str.append(getWeek(cal.get(Calendar.DAY_OF_WEEK)));
            return str.toString();
        } catch (Exception ex) {
            log.error("得到默认中文日期格式发生异常", ex);
        }
        return null;
    }
    
    /**
     * 得到中文星期
     * 
     * @param week 数字（1,2,3,4,5,6,7）
     * @return
     * @author guannan.shang
     */
    public static String getWeek(int week) {
        if (week <= 0 || week > 7)
            throw new IllegalArgumentException("week must be number 1-7![your week is " + week + "]");
        return weeks[week - 1];
    }
    
    public static String getSysOracleDate() {
        StringBuffer sb = new StringBuffer();
        String[] strs = new Date().toString().split(" ");
        sb.append(strs[2] + "-");
        sb.append(strs[1] + "-");
        sb.append(strs[5]);
        return sb.toString();
    }
    
    /**
     * 判断时间是同一天
     * 
     * @param time1
     * @param time2
     * @author guannan.shang
     * @return
     */
    public static boolean isSameDay(Date time1, Date time2) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(time1);
        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH);
        int day = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(time2);
        if (year != cal.get(Calendar.YEAR))
            return false;
        if (month != cal.get(Calendar.MONTH))
            return false;
        if (day != cal.get(Calendar.DAY_OF_MONTH))
            return false;
        return true;
    }
    /**
     * 判断是否是下午
     * @return boolean true：是；false:不是
     * 
     */
    public static boolean isAfternoon() {
		Calendar calendar = Calendar.getInstance();
		int now = calendar.get(Calendar.HOUR_OF_DAY);
		int flg = now - 12;
		if (flg > 0) {
			return true;
		} else {
			return false;
		}
	}	
    
    /**
     * 判断时间是今天
     * 
     * @param time
     * @return
     * @author guannan.shang
     */
    public static boolean isToday(Date time) {
        return isSameDay(new Date(), time);
    }

    /**
     * 获取上月最后一天
     * @param date
     * @return
     */
    public static Date getPreMonthLastDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 0);
        return cal.getTime();
    }

    /**
     * 判断日期是否是在一个时间范围内 
     * date大于start并且 date小于end时，返回true
     * @param start
     * @param end
     * @return 
     */
    public static boolean between(Date date, Date start, Date end) {
        if(date.compareTo(end)<=0 &&  date.compareTo(start)>0) {
            return true;
        }else {
            return false;
        }
    }
    /**
     * 把前台传过来的yyyy-MM-dd转化成yyyyMMdd格式的日期字符串
     * @param start
     * @param end
     * @return
     */
    public static String getStringdate(String date){
    	String[] datestr=date.split("-");
    	StringBuffer sb = new StringBuffer();
    	for(int i=0;i<datestr.length;i++){
    		sb.append(datestr[i]);
    	}
    	return sb.toString();
    }
    /**
     * 把前台传过来的yyyy-MM-dd转化成yyyy-MM-dd格式的日期格式
     * @param start
     * @param end
     * @return
     */
    public static Date strToDate(String strDate){
    	String jdkDateFormat="yyyy-MM-dd";
    	SimpleDateFormat dateFormat = new SimpleDateFormat(jdkDateFormat);
    	Date date = null;
    	try{ 
    		date = dateFormat.parse(strDate); 
    	}catch(ParseException e){
    		System.out.println(e.getMessage());
    	} 
    	return date; 
    }
    //把时间转化成yyyyMMdd格式的日期
    public static String dateToString(Date date){
    	SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
    	String time = format.format(date);
    	return time;
    }
    //获取当前时间的前一天格式yyyy-MM-dd
    public static String getbeforeDate(){
		Date date = DateUtils.getBeforeDay(new Date());
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		String beforedate = format.format(date);
		return beforedate;
    }
    //获取指定时间的前一月或者是获取后一个月时间
    public static String getBeforeDate(Date date, String flag){
    	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(date);
    	if("sub".equals(flag)){
    		calendar.add(Calendar.MONTH, -1);//得到前一个月
    	}else if("add".equals(flag)){
    		calendar.add(Calendar.MONTH, +1);//得到后一个月
    	}
    	//String datetime = dateToString(calendar.getTime());
    	return simpleDateFormat.format(calendar.getTime());
    }

    //获取指定日期的后一天
    public static String getAfterDate(Date date, String flag){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if("sub".equals(flag)){
            calendar.add(Calendar.DATE, -1);//得到前一天
        }else if("add".equals(flag)){
            calendar.add(Calendar.DATE, +1);//得到后一天
        }
        //String datetime = dateToString(calendar.getTime());
        return simpleDateFormat.format(calendar.getTime());
    }
  
    public static void main(String[] args) {
		String planDateStr = "2016-01-06 00:00:00";
		String operateDateStr = "2016-01-06 12:40:00";
		
		Date planDate = DateUtils.parseStringToDate(planDateStr);
    	Date operateDate = DateUtils.parseStringToDate(operateDateStr);
    	
//    	System.out.print(planDate.compareTo(operateDate));
    	String str = "start";
    	for(int i=0; i<100; i++){
    	str = str + "hello";
    	}
	}
    
    /**
	 * 根据时间获取该天的00分00秒
	 *
	 * @param d
	 * @return
	 */
	public static Date getZeroTimeOfDay(Date d) {
		if (d == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}

	/**
	 * 根据时间获取该天的最大时间
	 *
	 * @param d
	 * @return
	 */
	public static Date getMaxTimeOfDay(Date d) {
		if (d == null) {
			return null;
		}
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.set(Calendar.HOUR_OF_DAY, 23);
		c.set(Calendar.MINUTE, 59);
		c.set(Calendar.SECOND, 59);
		c.set(Calendar.MILLISECOND, 0);
		return c.getTime();
	}

	/**
	 * 把String类型转成时间类型
	 *
	 * @param d
	 * @return
	 */
	public static Date getStringToDate(String d) {
		if (StringUtils.isEmpty(d)) {
			return null;
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date date;
		try {
			date = sdf.parse(d);
			return date;
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 把date类型转成String类型
	 *
	 * @param d
	 * @return
	 */
	public static String getDateToString(Date d) {
		if (d == null) {
			return null;
		}
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String str = format.format(d);
		return str;

	}
}
